|
ARD2
RC2
Airbag Reference Demonstrator using MPC5604P
|
00001 00009 /*---------------------------------------------------------------------------*/ 00010 /* By default we do not use nested interrupts, interrupts are handled in C. */ 00011 /* In case you want to use nested interrupts, set INTC_NESTED_INTERRUPT. */ 00012 /* In this case make sure all the needed registers are saved in the prolog */ 00013 /* and epilog of asm void INTC_INTCInterruptHandler(void) */ 00014 /*---------------------------------------------------------------------------*/ 00015 00016 #ifndef INTC_NESTED_INTERRUPT 00017 #define INTC_NESTED_INTERRUPT 1 00018 #endif 00019 00020 /*---------------------------------------------------------------------------*/ 00021 /* Includes */ 00022 /*---------------------------------------------------------------------------*/ 00023 00024 #include "MPC5604P.h" /* MPC55xx platform development header */ 00025 00026 #include "IntcInterrupts.h" /* Implement functions from this file */ 00027 00028 /*---------------------------------------------------------------------------*/ 00029 /* Inline Assembler Defines */ 00030 /*---------------------------------------------------------------------------*/ 00031 00033 #define MAKE_HLI_ADDRESS(hli_name, c_expr) /*lint -e753 */enum { hli_name=/*lint -e30*/((int)(c_expr)) /*lint -esym(749, hli_name) */ }; 00034 00036 MAKE_HLI_ADDRESS(INTC_IACKR, &INTC.IACKR.R) 00038 MAKE_HLI_ADDRESS(INTC_EOIR, &INTC.EOIR.R) 00039 00041 MAKE_HLI_ADDRESS(INTC_MCR, &INTC.MCR.R) 00042 00043 /*---------------------------------------------------------------------------*/ 00044 /* Function Implementations */ 00045 /*---------------------------------------------------------------------------*/ 00046 00048 #define INTC_INTERRUPTS_REQUEST_VECTOR_TABLE_SIZE (308*4) 00049 00050 #pragma push /* Save the current state */ 00051 #pragma section data_type ".__initialized_intc_handlertable" ".__uninitialized_intc_handlertable" 00052 /* The INTC vector table will be placed in RAM. 00053 We will use the ".__uninitialized_intc_handlertable" name to do the 00054 placement in the Linker Command File (.lcf) to avoid the initialization at 00055 startup time. This will decrease the code size, but the table won't be 00056 initialized to zero. 00057 */ 00058 INTCInterruptFn INTCInterruptsHandlerTable[INTC_INTERRUPTS_REQUEST_VECTOR_TABLE_SIZE]; 00059 #pragma pop 00060 00061 #pragma push /* save the current state */ 00062 #pragma force_active on 00063 #pragma function_align 16 /* We use 16 bytes alignment for Exception handlers */ 00064 00066 #if INTC_NESTED_INTERRUPT == 0 00067 00068 __declspec(interrupt) 00069 __declspec(section ".__exception_handlers") 00070 void INTC_INTCInterruptHandler(void) 00071 { 00072 INTCInterruptFn *handlerFn = (INTCInterruptFn*)(*(unsigned int*)&INTC.IACKR.R); 00073 00074 (**handlerFn)(); 00075 00076 INTC.EOIR.R = 0; 00077 } 00078 00079 #else 00080 00081 __declspec(interrupt) 00082 __declspec(section ".__exception_handlers") 00083 __asm void INTC_INTCInterruptHandler(void) 00084 { 00085 nofralloc 00086 prolog: 00087 stwu r1, -0x50 (r1) /* Create stack frame */ 00088 stw r0, 0x24 (r1) /* Store r0 working register */ 00089 00090 /* Save SRR0 and SRR1 */ 00091 mfsrr1 r0 /* Store SRR1 (must be done before enabling EE) */ 00092 stw r0, 0x10 (r1) 00093 mfsrr0 r0 /* Store SRR0 (must be done before enabling EE) */ 00094 stw r0, 0x0C (r1) 00095 00096 /* Clear request to processor; r3 contains the address of the ISR */ 00097 stw r3, 0x28 (r1) /* Store r3 */ 00098 lis r3, INTC_IACKR@h /* Read pointer into ISR Vector Table & store in r3 */ 00099 ori r3, r3, INTC_IACKR@l 00100 lwz r3, 0x0(r3) /* Load INTC_IACKR, which clears request to processor */ 00101 lwz r3, 0x0(r3) /* Read ISR address from ISR Vector Table using pointer */ 00102 00103 /* Enable processor recognition of interrupts */ 00104 wrteei 1 /* Set MSR[EE]=1 */ 00105 00106 /* Save rest of context required by EABI */ 00107 stw r12, 0x4C (r1) /* Store r12 */ 00108 stw r11, 0x48 (r1) /* Store r11 */ 00109 stw r10, 0x44 (r1) /* Store r10 */ 00110 stw r9, 0x40 (r1) /* Store r9 */ 00111 stw r8, 0x3C (r1) /* Store r8 */ 00112 stw r7, 0x38 (r1) /* Store r7 */ 00113 stw r6, 0x34 (r1) /* Store r6 */ 00114 stw r5, 0x30 (r1) /* Store r5 */ 00115 stw r4, 0x2C (r1) /* Store r4 */ 00116 mfcr r0 /* Store CR */ 00117 stw r0, 0x20 (r1) 00118 mfxer r0 /* Store XER */ 00119 stw r0, 0x1C (r1) 00120 mfctr r0 /* Store CTR */ 00121 stw r0, 0x18 (r1) 00122 mflr r0 /* Store LR */ 00123 stw r0, 0x14 (r1) 00124 00125 /* Branch to ISR handler address from SW vector table */ 00126 mtlr r3 /* Store ISR address to LR to use for branching later */ 00127 blrl /* Branch to ISR, but return here */ 00128 00129 epilog: 00130 /* Restore context required by EABI (except working registers) */ 00131 lwz r0, 0x14 (r1) /* Restore LR */ 00132 mtlr r0 00133 lwz r0, 0x18 (r1) /* Restore CTR */ 00134 mtctr r0 00135 lwz r0, 0x1C (r1) /* Restore XER */ 00136 mtxer r0 00137 lwz r0, 0x20 (r1) /* Restore CR */ 00138 mtcrf 0xff, r0 00139 lwz r5, 0x30 (r1) /* Restore r5 */ 00140 lwz r6, 0x34 (r1) /* Restore r6 */ 00141 lwz r7, 0x38 (r1) /* Restore r7 */ 00142 lwz r8, 0x3C (r1) /* Restore r8 */ 00143 lwz r9, 0x40 (r1) /* Restore r9 */ 00144 lwz r10, 0x44 (r1) /* Restore r10 */ 00145 lwz r11, 0x48 (r1) /* Restore r11 */ 00146 lwz r12, 0x4C (r1) /* Restore r12 */ 00147 00148 /* Disable processor recognition of interrupts */ 00149 wrteei 0 00150 00151 /* Ensure interrupt flag has finished clearing */ 00152 mbar 0 00153 00154 /* Write 0 to INTC_EOIR, informing INTC to lower priority */ 00155 li r3, 0 00156 lis r4, INTC_EOIR@h /* Load upper half of INTC_EOIR address to r4 */ 00157 ori r4, r4, INTC_EOIR@l 00158 stw r3, 0(r4) /* Write 0 to INTC_EOIR */ 00159 00160 /* Restore Working Registers */ 00161 lwz r3, 0x28 (r1) /* Restore r3 */ 00162 lwz r4, 0x2C (r1) /* Restore r4 */ 00163 00164 /* Retrieve SRR0 and SRR1 */ 00165 lwz r0, 0x0C (r1) /* Restore SRR0 */ 00166 mtsrr0 r0 00167 lwz r0, 0x10 (r1) /* Restore SRR1 */ 00168 mtsrr1 r0 00169 00170 /* Restore Other Working Registers */ 00171 lwz r0, 0x24 (r1) /* Restore r0 */ 00172 00173 /* Restore space on stack */ 00174 addi r1, r1, 0x50 00175 00176 /* End of Interrupt */ 00177 rfi 00178 } 00179 00180 #endif 00181 00182 #pragma force_active off 00183 #pragma pop 00184 00190 void INTC_InstallINTCInterruptHandler(INTCInterruptFn handlerFn, unsigned short vectorNum, 00191 unsigned char psrPriority) 00192 { 00193 /* Set the function pointer in the ISR Handler table */ 00194 INTCInterruptsHandlerTable[vectorNum] = handlerFn; 00195 /* Set the PSR Priority */ 00196 INTC.PSR[vectorNum].B.PRI = psrPriority; 00197 } 00198 00203 __asm void INTC_InitINTCInterrupts( void ) 00204 { 00205 nofralloc 00206 00207 mflr r29 00208 00209 /* IVOR4 is for external interrupts (special purpose register #404) 00210 * This code enables the ISR handler for external interrupt code to address 00211 * INTC_INTCInterruptHandler (incl. large address by setting the IVPR value). 00212 */ 00213 lis r0, INTC_INTCInterruptHandler@h 00214 ori r0, r0, INTC_INTCInterruptHandler@l 00215 00216 #if !defined(Z0H_CORE) 00217 mtivor4 r0 00218 #else 00219 /* Set INTC.MCR = 0 VTES 4-bytes, HVEN - SW vector mode */ 00220 lis r0,0 00221 lis r3,INTC_MCR@ha 00222 stw r0, INTC_MCR@l(r3) 00223 #endif 00224 00225 /* Enable external interrupts in the Machine State Register. Set MSR[EE]=1. */ 00226 wrteei 1 00227 00228 /* Set the location of the ISR Handler Table in INTC IACKR Register */ 00229 lis r0, INTCInterruptsHandlerTable@h 00230 ori r0, r0, INTCInterruptsHandlerTable@l 00231 lis r3,INTC_IACKR@h 00232 ori r3,r3,INTC_IACKR@l 00233 stw r0, 0(r3) 00234 00235 mtlr r29 00236 00237 blr 00238 } 00239